c/c++开发分享ffmpeg解码音视频过程(附代码) 您所在的位置:网站首页 音视频解码 ffmpeg c/c++开发分享ffmpeg解码音视频过程(附代码)

c/c++开发分享ffmpeg解码音视频过程(附代码)

2022-06-10 10:58| 来源: 网络整理| 查看: 265

c/c++开发分享ffmpeg解码音视频过程(附代码) 唯美的心 • 2021年5月11日 上午10:04 • C/C++开发 • 阅读 66

0. 引言 最近一直在使用和学习ffmpeg. 工作中需要拉流解码, 获取音频和视频数据. 这些都是使用ffmpeg处理. 因为对ffmpeg接触不多, 用的不深, 在使用的过程中经常遇到不太懂的地方, 就会花费很多时间去查阅资料. 所以自己对用到的知识点总结一下, 方便自己以后再重复用到时能够方便 …

0. 引言 最近一直在使用和学习ffmpeg. 工作中需要拉流解码, 获取音频和视频数据. 这些都是使用ffmpeg处理.

  因为对ffmpeg接触不多, 用的不深, 在使用的过程中经常遇到不太懂的地方, 就会花费很多时间去查阅资料. 所以自己对用到的知识点总结一下, 方便自己以后再重复用到时能够方便找到.

  环境: ubuntu16.04, 已安装ffmpeg依赖库. gcc编译工具.

ffmpeg解码过程中用到了两个很重要的结构体, 这两个结构体比较复杂, 用到的次数也非常多, 以后我单独写一篇进行总结. avpacket 保存未解码的数据. avframe 保存解码后的数据.

 

1. 解码流程

ffmpeg解码音视频过程(附代码)

 

 2. 代码 1 //*************************************************************** 2 // @file: test.c 3 // @author: dingfang 4 // @date 2019-07-24 18:55:16 5 //*************************************************************** 6 7 #include 8 9 #ifdef __cplusplus 10 extern "c" 11 { 12 #endif 13 #include 14 #include 15 #ifdef __cplusplus 16 }; 17 #endif 18 19 int opencodeccontext(const avformatcontext *pformatctx, int *pstreamindex, enum avmediatype type, avcodeccontext **ppcodecctx) 20 { 21 int streamidx = -1; 22 // 获取流下标 23 for (int i = 0; i < pformatctx->nb_streams; i++) 24 { 25 if (pformatctx->streams[i]->codec->codec_type == type) 26 { 27 streamidx = i; 28 break; 29 } 30 } 31 if (streamidx == -1) 32 { 33 printf("find video stream failed!n"); 34 exit(-2); 35 } 36 // 寻找解码器 37 avcodeccontext *pcodecctx = pformatctx->streams[streamidx]->codec; 38 avcodec *pcodec = avcodec_find_decoder(pcodecctx->codec_id); 39 if (null == pcodec) 40 { 41 printf("avcode find decoder failed!n"); 42 exit(-2); 43 } 44 45 //打开解码器 46 if (avcodec_open2(pcodecctx, pcodec, null) < 0) 47 { 48 printf("avcode open failed!n"); 49 exit(-2); 50 } 51 *ppcodecctx = pcodecctx; 52 *pstreamindex = streamidx; 53 54 return 0; 55 } 56 57 int main(void) 58 { 59 avformatcontext *pinformatctx = null; 60 avcodeccontext *pvideocodecctx = null; 61 avcodeccontext *paudiocodecctx = null; 62 avpacket *ppacket = null; 63 avframe *pframe = null; 64 int ret; 65 /* 支持本地文件和网络url */ 66 const char streamurl[] = "./test.flv"; 67 68 /* 1. 注册 */ 69 av_register_all(); 70 71 pinformatctx = avformat_alloc_context(); 72 73 /* 2. 打开流 */ 74 if(avformat_open_input(&pinformatctx, streamurl, null, null) != 0) 75 { 76 printf("couldn't open input stream.n"); 77 return -1; 78 } 79 80 /* 3. 获取流的信息 */ 81 if(avformat_find_stream_info(pinformatctx, null) < 0) 82 { 83 printf("couldn't find stream information.n"); 84 return -1; 85 } 86 87 int videostreamidx = -1; 88 int audiostreamidx = -1; 89 /* 4. 寻找并打开解码器 */ 90 opencodeccontext(pinformatctx, &videostreamidx, avmedia_type_video, &pvideocodecctx); 91 opencodeccontext(pinformatctx, &audiostreamidx, avmedia_type_audio, &paudiocodecctx); 92 93 ppacket = av_packet_alloc(); 94 pframe = av_frame_alloc(); 95 96 int cnt = 30; 97 while (cnt--) 98 { 99 /* 5. 读流数据, 未解码的数据存放于ppacket */ 100 ret = av_read_frame(pinformatctx, ppacket); 101 if (ret < 0) 102 { 103 printf("av_read_frame errorn"); 104 break; 105 } 106 107 /* 6. 解码, 解码后的数据存放于pframe */ 108 /* 视频解码 */ 109 if (ppacket->stream_index == videostreamidx) 110 { 111 avcodec_decode_video2(pvideocodecctx, pframe, &ret, ppacket); 112 if (ret == 0) 113 { 114 printf("video decodec error!n"); 115 continue; 116 } 117 printf("* * * * * * video * * * * * * * * *n"); 118 printf("___height: [%d]n", pframe->height); 119 printf("____width: [%d]n", pframe->width); 120 printf("pict_type: [%d]n", pframe->pict_type); 121 printf("___format: [%d]n", pframe->format); 122 printf("* * * * * * * * * * * * * * * * * * *nn"); 123 } 124 125 /* 音频解码 */ 126 if (ppacket->stream_index == audiostreamidx) 127 { 128 avcodec_decode_audio4(paudiocodecctx, pframe, &ret, ppacket); 129 if (ret < 0) 130 { 131 printf("audio decodec error!n"); 132 continue; 133 } 134 printf("* * * * * * audio * * * * * * * * * *n"); 135 printf("____nb_samples: [%d]n", pframe->nb_samples); 136 printf("__samples_rate: [%d]n", pframe->sample_rate); 137 printf("channel_layout: [%lu]n", pframe->channel_layout); 138 printf("________format: [%d]n", pframe->format); 139 printf("* * * * * * * * * * * * * * * * * * *nn"); 140 } 141 av_packet_unref(ppacket); 142 } 143 144 av_frame_free(&pframe); 145 av_packet_free(&ppacket); 146 avcodec_close(pvideocodecctx); 147 avcodec_close(paudiocodecctx); 148 avformat_close_input(&pinformatctx); 149 150 return 0; 151 }

该代码不能直接编译, 编译需要依赖ffmpeg库. 包含ffmpeg动态库和makefile文件的压缩包地址:

解压后, 进入目录, 使用make命令即可编译.

 

3. 函数说明

这里就几个比较重要的函数简单介绍一下.

av_register_all()        /* 使用ffmpeg几乎都要调用这一个函数, 注册ffmpeg各种编解码器, 复用器等. */

avformat_open_input()      /* 该函数用于打开本地多媒体文件或者网络流媒体url */

avformat_find_stream_info()   /* 该函数用于读取一部分音视频数据并且获得一些相关的信息 */

avcodec_find_decoder()    /* 由codec_id或者解码器名称来寻找对应的解码器 */

avcodec_open2()        /* 初始化解码器 */

av_read_frame()        /* 读流数据, 读出来的是压缩数据, 存放于avpacket */

avcodec_decode_video2()    /* 视频解码 解码后数据为原始数据, 存放于avframe */

avcodec_decode_audio4()    /* 音频解码 解码后数据为原始数据, 存放于avframe */

 

 

 

本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ssfiction.com/c-cyuyankaifa/602576.html

CCODEAFailformGCChhttpIDEinputnsOGpsSEstreamUbuntuVP工具数据 赞 (0) 唯美的心唯美的心 0 0 生成海报


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有